package com.luboyan.CBillbill.service.file.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.luboyan.CBillbill.dao.user.UserPreference;
import com.luboyan.CBillbill.exception.ConditionException;
import com.luboyan.CBillbill.dao.file.*;
import com.luboyan.CBillbill.dao.user.User;
import com.luboyan.CBillbill.dao.user.UserCoin;
import com.luboyan.CBillbill.dao.user.UserInfo;
import com.luboyan.CBillbill.dao.vo.PageVo;
import com.luboyan.CBillbill.mapper.file.*;
import com.luboyan.CBillbill.service.file.VideoService;
import com.luboyan.CBillbill.service.user.UserCoinService;
import com.luboyan.CBillbill.service.user.UserService;
import com.luboyan.CBillbill.util.FastDFSUtil;
import com.luboyan.CBillbill.util.IpUtil;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericPreference;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.UncenteredCosineSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class VideoServiceImpl implements VideoService {

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    private VideoTagMapper videoTagMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private VideoLikeMapper videoLikeMapper;

    @Autowired
    private VideoCollectionMapper videoCollectionMapper;

    @Autowired
    private CollectionGroupMapper collectionGroupMapper;

    @Autowired
    private VideoCoinMapper videoCoinMapper;

    @Autowired
    private VideoCommentMapper videoCommentMapper;

    @Autowired
    private VideoViewMapper videoViewMapper;

    @Autowired
    private VideoOperationMapper videoOperationMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private UserCoinService userCoinService;

    @Autowired
    private FastDFSUtil fastDFSUtil;

    /**
     * 新增视频
     */
    @Override
    @Transactional
    public void addVideos(Video video) {
        video.setCreateTime(new Date());
        videoMapper.insert(video);
        Long videoId = video.getId();
        List<VideoTag> tagList = video.getVideoTagList();
        tagList.forEach(item -> {
            item.setCreateTime(new Date());
            item.setVideoId(videoId);
        });
        //有待优化
        for (VideoTag tag : tagList) {
            if (tag.getTagId() == null) {
                Tag tagName = new Tag();
                tagName.setName(tag.getTagName());
                tagName.setCreateTime(new Date());
                tagMapper.insert(tagName);
                Long tagId = tagName.getId();
                tag.setTagId(tagId);
            }
            videoTagMapper.insert(tag);
        }
    }

    /**
     * 根据分区分页返回视频
     */
    @Override
    public PageVo<Video> pageVoVideos(Integer page, Integer pageSize, String area) {
        if (page == null || pageSize == null) {
            throw new ConditionException("参数异常！");
        }
        JSONObject params = new JSONObject();
        params.put("start", (page - 1) * pageSize);
        params.put("limit", pageSize);
        params.put("area", area);
        List<Video> videoList = new ArrayList<>();
        QueryWrapper<Video> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("area", area);
        Long total = videoMapper.selectCount(queryWrapper);
        if (total > 0) {
            videoList = videoMapper.getPageListVideos(params);
            videoList = getTag(videoList);
        }
        return new PageVo<>(Integer.parseInt(Long.toString(total)), videoList);
    }

    /**
     * 获取所有视频分页返回
     */
    @Override
    public PageVo<Video> pageVoAllVideos(Integer page, Integer pageSize) {
        if (page == null || pageSize == null) {
            throw new ConditionException("参数异常！");
        }
        JSONObject params = new JSONObject();
        params.put("start", (page - 1) * pageSize);
        params.put("limit", pageSize);
        List<Video> videoList = new ArrayList<>();
        videoList = videoMapper.getPageAllListVideos(params);
        videoList = getTag(videoList);
        return new PageVo<>(videoList.size(), videoList);
    }

    /***
     * 查询标签
     */
    @Override
    public ArrayList<Tag> getTags() {
        QueryWrapper<Tag> tagQueryWrapper = new QueryWrapper<>();
        tagQueryWrapper.last("LIMIT 5");
        List<Tag> tags = tagMapper.selectList(tagQueryWrapper);
        ArrayList<Tag> tagArrayList = new ArrayList<>(tags.size());
        tagArrayList.addAll(tags);
        return tagArrayList;
    }

    /**
     * 根据用户id返回视频
     */
    @Override
    public PageVo<Video> getVideosByUserId(Integer page, Integer pageSize, Long userId) {
        if (page == null || pageSize == null) {
            throw new ConditionException("参数异常！");
        }
        JSONObject params = new JSONObject();
        params.put("start", (page - 1) * pageSize);
        params.put("limit", pageSize);
        params.put("userId", userId);
        List<Video> videoList = new ArrayList<>();
        QueryWrapper<Video> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        Long total = videoMapper.selectCount(queryWrapper);
        if (total > 0) {
            videoList = videoMapper.getPageListVideosByUserId(params);
            videoList = getTag(videoList);
        }
        return new PageVo<>(Integer.parseInt(Long.toString(total)), videoList);
    }

    /***
     * 给视频打上标签
     */
    public List<Video> getTag(List<Video> videoList){
        for (Video video : videoList) {
            //先通过videoId获取这个视频所拥有的所有tagId
            QueryWrapper<VideoTag> videoTagQueryWrapper = new QueryWrapper<>();
            videoTagQueryWrapper.eq("videoId", video.getId());
            List<VideoTag> videoTags = videoTagMapper.selectList(videoTagQueryWrapper);
            //通过tagId获取标签名称
            for (VideoTag videoTag: videoTags){
                Tag tag = tagMapper.selectById(videoTag.getTagId());
                videoTag.setTagName(tag.getName());
            }
            video.setVideoTagList(videoTags);
        }
        return videoList;
    }

    /**
     * 根据videoId获取视频
     */
    @Override
    public Video getVideoById(Long videoId) {
        return videoMapper.selectById(videoId);
    }

    /**
     * 分片下载视频,通过流进行传输
     */
    @Override
    public void getVideosByShard(HttpServletRequest request, HttpServletResponse response, String path) throws Exception {
        fastDFSUtil.getVideosByShard(request, response, path);
    }

    /**
     * 点赞视频
     */
    @Override
    @Transactional
    public void addVideoLike(Long videoId, Long userId) {
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频！");
        }
        QueryWrapper<VideoLike> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).eq("userId", userId);
        VideoLike videoLike = videoLikeMapper.selectOne(queryWrapper);
        if (videoLike != null) {
            throw new ConditionException("已经赞过！");
        }
        videoLike = new VideoLike();
        videoLike.setVideoId(videoId);
        videoLike.setUserId(userId);
        videoLike.setCreateTime(new Date());
        videoLikeMapper.insert(videoLike);

        VideoOperation videoOperation = new VideoOperation();
        videoOperation.setVideoId(videoId);
        videoOperation.setUserId(userId);
        videoOperation.setCreateTime(new Date());
        videoOperation.setOperationType("1");
        videoOperationMapper.insert(videoOperation);

    }

    /**
     * 取消点赞
     */
    @Override
    @Transactional
    public void deleteVideoLike(Long videoId, Long userId) {
        QueryWrapper<VideoLike> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).eq("userId", userId);
        VideoLike videoLike = videoLikeMapper.selectOne(queryWrapper);
        if (videoLike == null) {
            throw new ConditionException("还未点赞！");
        }
        videoLikeMapper.delete(queryWrapper);

        videoOperationMapper.delete(
                new QueryWrapper<VideoOperation>()
                        .eq("userId", userId)
                        .eq("videoId", videoId)
                        .eq("operationType", "1"));
    }

    /**
     * 查询视频点赞
     */
    @Override
    public Map<String, Object> getVideoLikes(Long videoId, Long userId) {
        QueryWrapper<VideoLike> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId);
        Long count = videoLikeMapper.selectCount(queryWrapper);
        boolean like = false;
        if (userId != null) {
            queryWrapper.eq("userId", userId);
            VideoLike videoLike = videoLikeMapper.selectOne(queryWrapper);
            if (videoLike != null) {
                like = true;
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("like", like);
        return result;
    }

    /**
     * 收藏视频
     */
    @Override
    @Transactional
    public void addVideoCollections(VideoCollection videoCollection, Long userId) {
        Long videoId = videoCollection.getVideoId();
        Long groupId = videoCollection.getGroupId();
        if (videoId == null) {
            throw new ConditionException("参数异常！");
        }
        if (groupId == null) {
            groupId = 1L;
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频！");
        }
        QueryWrapper<VideoCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).eq("userId", userId);
        videoCollectionMapper.delete(queryWrapper);
        videoCollection.setUserId(userId);
        videoCollection.setCreateTime(new Date());
        videoCollection.setGroupId(groupId);
        videoCollectionMapper.insert(videoCollection);

        VideoOperation videoOperation = new VideoOperation();
        videoOperation.setVideoId(videoId);
        videoOperation.setUserId(userId);
        videoOperation.setCreateTime(new Date());
        videoOperation.setOperationType("0");
        videoOperationMapper.insert(videoOperation);
    }

    /**
     * 取消收藏
     */
    @Override
    public void deleteVideoCollections(Long videoId, Long userId) {
        QueryWrapper<VideoCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).eq("userId", userId);
        videoCollectionMapper.delete(queryWrapper);

        videoOperationMapper.delete(
                new QueryWrapper<VideoOperation>()
                        .eq("userId", userId)
                        .eq("videoId", videoId)
                        .eq("operationType", "0"));
    }

    /**
     * 获取视频收藏量
     */
    @Override
    public Map<String, Object> getVideoCollections(Long videoId, Long userId) {
        QueryWrapper<VideoCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId);
        Long count = videoCollectionMapper.selectCount(queryWrapper);
        boolean like = false;
        if (userId != null) {
            queryWrapper.eq("userId", userId);
            VideoCollection videoCollection = videoCollectionMapper.selectOne(queryWrapper);
            if (videoCollection != null) {
                like = true;
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("like", like);
        return result;
    }

    /**
     * 用户添加视频关注分组
     */
    @Override
    public Long addUserFollowingGroups(CollectionGroup collectionGroup) {
        Long userId = collectionGroup.getUserId();
        String name = collectionGroup.getName();
        QueryWrapper<CollectionGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId).eq("name", name);
        CollectionGroup group = collectionGroupMapper.selectOne(queryWrapper);
        if (group != null) {
            throw new ConditionException("分组已存在！");
        }
        collectionGroup.setType("1");
        collectionGroup.setCreateTime(new Date());
        collectionGroupMapper.insert(collectionGroup);
        return collectionGroup.getId();
    }

    /**
     * 用户获取视频关注分组
     */
    @Override
    public List<CollectionGroup> getVideoCollectionGroup(Long userId) {
        return collectionGroupMapper.selectList(new QueryWrapper<CollectionGroup>().eq("userId", userId));
    }

    /**
     * 得到收藏视频
     *
     * @return 以分组的形式返回给前端
     */
    @Override
    public PageVo<Video> PageVideoCollectionGroup(Integer page, Integer pageSize, Long userId, Long groupId) {
        //查询用户关注的所有视频
        QueryWrapper<VideoCollection> videoCollectionQueryWrapper = new QueryWrapper<>();
        videoCollectionQueryWrapper.eq("userId", userId).eq("groupId", groupId);
        Long total = videoCollectionMapper.selectCount(videoCollectionQueryWrapper);
        if (total == 0) {
            throw new ConditionException("该分组无视频！");
        }
        page = (page - 1) * pageSize;
        List<VideoCollection> videoCollectionList = videoCollectionMapper.getVideoCollectionByUserId(page, pageSize, userId, groupId);
//        System.out.println(videoCollectionList.toString());

        //获取收藏视频的videoId，并且获取相应的视频信息
        List<Long> videoIds = new ArrayList<>();
        for (VideoCollection videoCollection : videoCollectionList) {
            videoIds.add(videoCollection.getVideoId());
        }
        List<Video> videoList = videoMapper.selectBatchIds(videoIds);


        return new PageVo<>(Integer.parseInt(String.valueOf(total)), videoList);
    }

    /**
     * 用户给视频进行投币
     */
    @Override
    @Transactional
    public void addVideoCoins(VideoCoin videoCoin, Long userId) {
        Long videoId = videoCoin.getVideoId();
        Integer amount = videoCoin.getAmount();
        if (videoId == null || amount == null) {
            throw new ConditionException("参数异常!");
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频!");
        }
        //先对用户的硬币数量进行查询
        UserCoin userCoinAmount = userCoinService.getUserCoinByUserId(userId);
        Integer coinAmount = userCoinAmount.getAmount();
        if (amount > coinAmount) {
            throw new ConditionException("硬币不足！");
        }
        //查询用户对视频的投票信息
        QueryWrapper<VideoCoin> videoCoinQueryWrapper = new QueryWrapper<>();
        videoCoinQueryWrapper.eq("userId", userId).eq("videoId", videoId);
        VideoCoin dbVideoCoin = videoCoinMapper.selectOne(videoCoinQueryWrapper);
        if (dbVideoCoin == null) {
            videoCoin.setCreateTime(new Date());
            videoCoin.setUserId(userId);
            videoCoinMapper.insert(videoCoin);
        } else {
            Integer dbAmount = dbVideoCoin.getAmount();
            Integer newAmount = dbAmount + amount;
            if (newAmount > 2) {
                throw new ConditionException("超过投币上限！");
            }
            dbVideoCoin.setAmount(newAmount);
            dbVideoCoin.setUpdateTime(new Date());
            videoCoinMapper.update(videoCoin, videoCoinQueryWrapper);
        }
        //更新用户硬币数
        userCoinAmount.setAmount(coinAmount - amount);
        userCoinAmount.setUpdateTime(new Date());
        userCoinService.updateUserCoins(userCoinAmount, userId);
        //更新用户对视频操作
        QueryWrapper<VideoOperation> videoOperationQueryWrapper = new QueryWrapper<>();
        videoOperationQueryWrapper
                .eq("userId", userId)
                .eq("videoId", videoId)
                .eq("operationType", "2");
        VideoOperation dbvideoOperation = videoOperationMapper.selectOne(videoOperationQueryWrapper);
        if (dbvideoOperation == null) {
            VideoOperation videoOperation = new VideoOperation();
            videoOperation.setVideoId(videoId);
            videoOperation.setUserId(userId);
            videoOperation.setCreateTime(new Date());
            videoOperation.setOperationType("2");
            videoOperationMapper.insert(videoOperation);
        }

    }

    /**
     * 获取视频投币量
     */
    @Override
    public Map<String, Object> getVideoCoins(Long videoId, Long userId) {
        QueryWrapper<VideoCoin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).select("sum(amount) as sum_amount");
        Map<String, Object> videoCoins = videoCoinMapper.selectMaps(queryWrapper).get(0);
        BigDecimal sum_amount = (BigDecimal) videoCoins.get("sum_amount");
        boolean like = false;
        if (userId != null) {
            queryWrapper.clear();
            queryWrapper.eq("userId", userId).eq("videoId", videoId);
            VideoCoin dbVideoCoin = videoCoinMapper.selectOne(queryWrapper);
            if (dbVideoCoin != null) {
                like = true;
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("count", sum_amount);
        result.put("like", like);
        return result;
    }

    /**
     * 添加视频评论
     */
    @Override
    public void addVideoComments(VideoComment videoComment, Long userId) {
        Long videoId = videoComment.getVideoId();
        if (videoId == null) {
            throw new ConditionException("非法视频！");
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频!");
        }
        videoComment.setUserId(userId);
        videoComment.setCreateTime(new Date());
        videoCommentMapper.insert(videoComment);
    }

    /**
     * 查询视频评论
     */
    @Override
    public PageVo<VideoComment> PageGetVideoComments(Integer page, Integer pageSize, Long videoId) {
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频!");
        }
        JSONObject params = new JSONObject();
        params.put("start", (page - 1) * pageSize);
        params.put("limit", pageSize);
        params.put("videoId", videoId);

        //查询出一级评论的数量
        QueryWrapper<VideoComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("videoId", videoId).isNull("rootId");
        Long total = videoCommentMapper.selectCount(queryWrapper);

        List<VideoComment> videoCommentList = new ArrayList<>();
        if (total > 0) {
            //查询出所有一级评论
            videoCommentList = videoCommentMapper.PageGetVideoComments(params);
            //收集一级评论的id
            List<Long> parentList = videoCommentList.stream().map(VideoComment::getId).collect(Collectors.toList());
            //通过一级评论id去查询对应的二级评论
            queryWrapper.clear();
            queryWrapper.in("rootId", parentList);
            List<VideoComment> childCommentList = videoCommentMapper.selectList(queryWrapper);
            //通过二级评论的两个userId查出评论用户和被评论用户的消息
            Set<Long> userIdList = videoCommentList.stream().map(VideoComment::getUserId).collect(Collectors.toSet());
            Set<Long> replyUserIdList = childCommentList.stream().map(VideoComment::getReplyUserId).collect(Collectors.toSet());
            userIdList.addAll(replyUserIdList); //合并在一起得到所有用户的ids
            List<UserInfo> userInfoList = userService.getUserInfoByIds(userIdList); //批量查询信息
            Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getUserId, userInfo -> userInfo));

            //开始映射
            for (VideoComment videoComment : videoCommentList) {
                List<VideoComment> childComment = new ArrayList<>();
                for (VideoComment child : childCommentList) {
                    if (videoComment.getId().equals(child.getRootId())) {
                        child.setUserInfo(userInfoMap.get(child.getUserId()));
                        child.setReplyUserInfo(userInfoMap.get(child.getReplyUserId()));
                        childComment.add(child);
                    }
                    videoComment.setChildList(childComment);
                    videoComment.setUserInfo(userInfoMap.get(child.getUserId()));
                }
            }

        }
        return new PageVo<>(Integer.parseInt(String.valueOf(total)), videoCommentList);
    }


    /**
     * 获取视频详情
     */
    @Override
    public Map<String, Object> getVideoDetails(Long videoId) {
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频!");
        }
        Long userId = video.getUserId();
        User user = userService.getUserInfo(userId);
        UserInfo userInfo = user.getUserInfo();
        HashMap<String, Object> result = new HashMap<>();
        result.put("video", video);
        result.put("userInfo", userInfo);
        return result;
    }

    /**
     * 添加视频观看记录
     */
    @Override
    public void addVideoView(VideoView videoView, HttpServletRequest request) {
        Long userId = videoView.getUserId();
        Long videoId = videoView.getVideoId();
        if (videoId == null) {
            throw new ConditionException("非法参数！");
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            throw new ConditionException("非法视频！");
        }

        String agent = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(agent);
        String clientId = String.valueOf(userAgent.getId());
        String ip = IpUtil.getIP(request);
        Map<String, Object> params = new HashMap<>();
        //区分用户和游客的判断条件
        if (userId != null) {
            params.put("userId", userId);
        } else {
            params.put("ip", ip);
            params.put("clientId", clientId);
        }
        //判断当天是否已经有记录
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        params.put("today", sdf.format(now));
        params.put("videoId", videoId);
        //添加
        VideoView dbVideoView = videoViewMapper.getVideoViews(params);
        if (dbVideoView == null) {
            videoView.setIp(ip);
            videoView.setClientId(clientId);
            videoView.setCreateTime(new Date());
            videoViewMapper.insert(videoView);
        }
    }

    /**
     * 查询视频播放量
     */
    @Override
    public Integer getVideoViewCounts(Long userId) {
        QueryWrapper<VideoView> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        Long count = videoViewMapper.selectCount(queryWrapper);
        return Integer.parseInt(String.valueOf(count));
    }

    /**
     * 视频推荐（基于用户）
     */
    @Override
    public List<Video> recommend(Long userId) throws TasteException {
        List<UserPreference> userPreferenceList = videoMapper.getAllUserPreference();
        DataModel dataModel = this.createDataModel(userPreferenceList);
        //计算用户相似度
        UserSimilarity similarity = new UncenteredCosineSimilarity(dataModel);
        //获取相似用户,这里获得了n个
        UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(2, similarity, dataModel);
        //构造推荐器
        Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, similarity);
        //推荐,结果会是一串id
        List<RecommendedItem> recommendedItems = recommender.recommend(userId, 5); //给userId推荐n个
        List<Long> itemIds = recommendedItems.stream().map(RecommendedItem::getItemID).collect(Collectors.toList());
        if (itemIds.isEmpty()) {
            return null;
        }
        return videoMapper.selectBatchIds(itemIds);
    }

    /**
     * 基于内容的协同推荐
     *
     * @param userId  用户id
     * @param itemId  参考内容id（根据该内容进行相似内容推荐）
     * @param howMany 需要推荐的数量
     */
    public List<Video> recommendByItem(Long userId, Long itemId, int howMany) throws TasteException {
        List<UserPreference> list = videoMapper.getAllUserPreference();
        //创建数据模型
        DataModel dataModel = this.createDataModel(list);
        //获取内容相似程度
        ItemSimilarity similarity = new UncenteredCosineSimilarity(dataModel);
        GenericItemBasedRecommender genericItemBasedRecommender = new GenericItemBasedRecommender(dataModel, similarity);
        // 物品推荐相拟度，计算两个物品同时出现的次数，次数越多任务的相拟度越高
        List<Long> itemIds = genericItemBasedRecommender.recommendedBecause(userId, itemId, howMany)
                .stream()
                .map(RecommendedItem::getItemID)
                .collect(Collectors.toList());
        //推荐视频
        return videoMapper.selectBatchIds(itemIds);
    }

    /**
     * 生成数据模型
     */
    private DataModel createDataModel(List<UserPreference> userPreferenceList) {
        FastByIDMap<PreferenceArray> fastByIDMap = new FastByIDMap<>();
        //将用户的所有视频得分按照userId进行分组
        Map<Long, List<UserPreference>> map =
                userPreferenceList.stream().collect(Collectors.groupingBy(UserPreference::getUserId));
        //得到所有用户的视频得分列表
        Collection<List<UserPreference>> lists = map.values();
        for (List<UserPreference> userPreferences : lists) {
            //需要将用户的行为映射到推荐引擎中，使用mahout提供的类
            GenericPreference[] array = new GenericPreference[userPreferences.size()];
            for (int i = 0; i < userPreferences.size(); i++) {
                UserPreference userPreference = userPreferences.get(i);
                //将关键列赋值（给谁推荐， 推荐什么， 得分多少）
                GenericPreference genericPreference = new GenericPreference(userPreference.getUserId(), userPreference.getVideoId(), userPreference.getValue());
                array[i] = genericPreference;
            }
            //userId对应自己的偏好得分,GenericUserPreferenceArray要求UserID相同，因为是建立基于用户的
            fastByIDMap.put(array[0].getUserID(), new GenericUserPreferenceArray(Arrays.asList(array)));
        }
        return new GenericDataModel(fastByIDMap);
    }
}


